package stendcontrol;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Random;
import java.util.TreeSet;
import javax.swing.JOptionPane;

public class DataProcessor {

    public final String CLASS_NAME = "Data processor";
    private double[] xs;
    private double baseLengths[] = {0.08, 0.25, 0.8, 2.5, 8.0};
    private double specSampIntrv;
    private double corSampIntrv;
    private static double avg;
    private static double mean_g;
    private static double dispersion;
    public double[] process;
    private static double beta_0 = 0;
    private static double beta_1 = 0;
    public static double betta[];
    public static double gm = 0;
    /* 
     * 
     * 0-Викерс;
     * 1-Роквул(НRA);
     * 2-Роквул(НRС);
     * 3-Бринель
     */

    public static void main(String[] args) {
        double x[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
        double y[] = {1.0, 1.1, 1.2, 1.21, 1.22, 1.23, 1.34, 1.4, 1.51, 1.52};
        double spec = 1.3;
        System.out.println("Result : " + Arrays.toString(new DataProcessor().
                fourierTransform(x, y, 5, spec)));
    }

    public String getCLASS_NAME() {
        return CLASS_NAME;
    }

    @Override
    public String toString() {
        return " This is " + getCLASS_NAME() + " class";
    }
    public int[][] hardnessTable = {
        /**
         * **************************Викерс**********************************
         */
        {1865, 1787, 1710, 1633, 1556, 1478, 1400, 1323, 1245, 1160, 1076, 1004,
            940, 900, 865, 832, 800, 772, 746, 720, 697, 674, 653, 633, 613, 595,
            577, 560, 544, 528, 513, 498, 484, 471, 458, 446, 434, 423, 412, 402,
            392, 382, 372, 363, 354, 345, 336, 327, 318, 310, 302, 294, 286, 279,
            272, 266, 260, 254, 248, 243, 238, 234, 230, 226, 222, 217, 213, 208,
            204, 200, 196, 192, 188, 184, 180, 176, 172, 168, 164, 160, 156, 152,
            48, 144, 141, 139, 137, 135, 132, 130, 127, 125, 123, 120, 118, 116,
            115, 114, 113, 112, 111, 110, 108, 107, 106, 105, 104, 103, 102, 101,
            100, 100, 99, 98, 97, 96, 95, 95, 94, 93, 92, 91, 90, 90, 89, 88, 88,
            87, 87, 86, 86, 85, 85, 84, 84, 83, 83, 82, 82, 81, 81, 80, 80, 79,
            79, 78, 78, 77, 77, 76, 76, 75, 75, 74, 74, 73, 73, 72, 72, 71, 71,
            70},
        /**
         * **************************Роквул(HRA)*****************************
         */
        {92, 92, 91, 91, 90, 90, 89, 89, 88, 87, 87, 86, 86, 85, 85, 84, 84, 83,
            83, 82, 81, 81, 80, 80, 79, 79, 78, 78, 77, 77, 76, 75, 75, 74, 74,
            73, 73, 72, 72, 71, 71, 70, 70, 69, 69, 68, 68, 67, 67, 66, 66, 65,
            65, 64, 64, 63, 63, 62, 62, 61, 61, 60, 59, 59, 58, 58, 58, 57, 57,
            56, 56, 56, 55, 54, 54, 53, 53, 52, 51, 51, 50, 50, 49, 49, 48, 47,
            47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 42, 41, 41, 40, 40, 39,
            39, 38, 38, 38, 37, 37, 36, 36, 35, 35, 35, 34, 34, 33, 33, 32, 32,
            31, 31, 31, 30, 30, 29, 29, 28, 28, 28, 27, 27, 26, 26, 25, 25, 24,
            24, 24, 23, 23, 22, 22, 21, 21, 21, 20},
        /**
         * **************************Роквул(HRС)*****************************
         */
        {80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63,
            62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46,
            45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29,
            28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12,
            11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0},
        /**
         * ************************Бринель(HRB)******************************
         */
        {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 739, 722,
            705, 688, 670, 654, 634, 615, 595, 577, 560, 543, 523, 512, 496, 481,
            469, 455, 443, 432, 421, 409, 400, 390, 381, 371, 362, 353, 344, 336,
            327, 319, 311, 301, 294, 286, 279, 271, 264, 258, 253, 247, 240, 234,
            228, 222, 218, 214, 210, 208, 205, 203, 200, 195, 193, 190, 185, 180,
            176, 172, 169, 165, 162, 159, 156, 153, 150, 147, 144, 141, 139, 137,
            135, 132, 130, 127, 125, 123, 121, 119, 117, 116, 114, 112, 110, 108,
            107, 106, 104, 102, 101, 99}
    };

    /**
     * Доступ к массиву базовых длин
     *
     * @return
     */
    public double[] getBaseLengths() {
        return baseLengths;
    }

    /**
     * Вернуть коэффициент бета0
     *
     * @return
     */
    public double getBeta0() {
        return beta_0;
    }

    /**
     * Вернуть коэффициент бета1
     *
     * @return
     */
    public double getBeta1() {
        return beta_1;
    }

    /**
     *
     * @param Тип величины, в которую конвертируется передаваемая твердость
     * @param val значение твердости, которую требуется конвертировать
     * @return величина твердости, конвертированная в требуемую
     */
    public int convertTo(int type, double val) {
        int res = 0, indx = 0;
        if (type > 0 && type < 4) {
            indx = findClosest((int) val);
            switch (type) {
                case 1: {
                    if (indx > hardnessTable[1].length - 1 || indx == -1) {
                        StendLogger.log(StendLogger.MSG_ERROR, "Value in HRA "
                                + "table doesn't exist");
                        res = -1;
                    } else {
                        res = hardnessTable[1][indx];
                    }
                }
                break;
                case 2: {
                    if (indx > hardnessTable[2].length - 1 || indx == -1) {
                        StendLogger.log(StendLogger.MSG_ERROR, "Value in HRC "
                                + "table doesn't exist");
                        res = -1;
                    } else {
                        res = hardnessTable[2][indx];
                    }
                }
                break;
                case 3: {
                    if (indx > hardnessTable[3].length - 1 || indx == -1) {
                        StendLogger.log(StendLogger.MSG_ERROR, "Value in Brinel "
                                + "table doesn't exist");
                        res = -1;
                    } else if (hardnessTable[3][indx] == - 1) {
                        StendLogger.log(StendLogger.MSG_ERROR, "Value in Brinel "
                                + "table doesn't exist");
                        res = -1;
                    } else {
                        res = hardnessTable[3][indx];
                    }
                }
                break;
            }
        } else {
            StendLogger.log(StendLogger.MSG_ERROR, "Function "
                    + "gets type numbers in this range: 1..3 ");
        }
        return res;
    }

    /**
     *
     * @param Значение, индекс которого требуется найти
     * @return индекс значения из таблицы
     */
    public int findClosest(int val) {
        int indx = 0;
        if (!(val < 70 || val > 1865)) {
            for (int i = hardnessTable[0].length - 1; i > -1; i--) {
                if (val < hardnessTable[0][i]) {
                    indx = i + 1;
                    break;
                } else {
                    if (val == hardnessTable[0][i]) {
                        indx = i;
                        break;
                    }
                }
            }
        } else {
            StendLogger.log(StendLogger.MSG_ERROR, "Value out of table");
            return -1;
        }
        return indx;
    }

    /**
     * Установка процесса
     *
     * @param proc
     * @param x
     */
    public void setProcess(double[] x, double[] proc) {
        mean_g = 0;
        dispersion = 0;
        //process = new double[proc.length];
        process = proc;
        xs = x;
    }

    /**
     * Поиск максимального значения выборки
     *
     * @return максимальное значение
     */
    public double getMaxValue() {
        return getMaxValue(process);
    }

    public static double getMaxValue(double[] proc) {
        double max = proc[0];
        for (int i = 0; i < proc.length; i++) {
            if (max < proc[i]) {
                max = proc[i];
            }
        }
        System.out.println("Max -> " + max);
        return max;
    }

    /**
     * Поиск минимального значения выборки
     *
     * @return минимальное значение
     */
    public double getMinValue() {
        return getMinValue(process);
    }

    public static double getMinValue(double[] proc) {
        double min = proc[0];
        for (int i = 0; i < proc.length; i++) {
            if (min > proc[i]) {
                min = proc[i];
            }
        }
        return min;
    }

    /**
     * Нахождение матожидания
     *
     * @return матожидание
     */
    public double getMean() {
        return getMean(process);
    }

    public static double getMean(double proc[]) {
        double mean = 0;
        mean = getMoment(1, false, proc);
        mean_g = mean;
        return mean;
    }

    /**
     * Нахождение дисперсии
     *
     * @return дисперсия
     */
    public double getDisp() {
        return getDisp(process);
    }

    public static double getDisp(double[] proc) {
        double disp = 0;
        disp = getMoment(2, true, proc);
        dispersion = disp;
        return disp;
    }

    public double[] filtrateProc(int n, double k) {
        double[] res = new double[process.length];
        double it = 0;
        double len = res.length;
        double sum = 0;
        int clone_n = 0;
        for (int l = 0; l <= (n / 2) + 1; l++) {
            clone_n = 0;
            sum = 0;
            for (int i = l - ((n + 1) / 2); i < l + (n / 2); i++) {
                if (i > -1 && i < len) {
                    sum += (process[i] * Math.exp(-k * Math.abs(xs[l] - xs[i])));
                    clone_n++;
                }
            }
            res[l] = sum / clone_n;
        }
        for (int l = n / 2 + 2; l <= len / 2 - 2; l++) {
            sum = 0;
            for (int i = l - ((n + 1) / 2); i < l + (n / 2); i++) {
                sum += (process[i] * Math.exp(-k * Math.abs(xs[l] - xs[i])));
            }
            res[l] = sum / n;
        }
        for (int l = (int) len / 2 - 1; l < len; l++) {
            clone_n = 0;
            sum = 0;
            for (int i = l - ((n + 1) / 2); i < l + (n / 2); i++) {
                if (i > -1 && i < len) {
                    sum += (process[i] * Math.exp(-k * Math.abs(xs[l] - xs[i])));
                    clone_n++;
                }
            }
            res[l] = sum / clone_n;
        }
        return res;
    }

    /**
     * Нахождение момента к-ого порядка
     *
     * @param order - порядок
     * @param central - вид момента
     * @return момент к-ого порядка
     */
    public static double getMoment(int order, boolean central, double[] proc) {
        double moment = 0, sum = 0, div = 0;
        double mean = 0;
        if (central) {
            if (mean_g == 0) {
                mean = getMean(proc);
            } else {
                mean = mean_g;
            }
            for (int i = 0; i < proc.length; i++) {
                div += Math.pow((proc[i] - mean), order);
            }
            moment = 1.0 / (proc.length - 1) * div;
        } else {
            for (int i = 0; i < proc.length; i++) {
                sum += Math.pow(proc[i], order);
            }
            moment = sum * Math.pow(proc.length, -1);
        }
        return moment;
    }

    /**
     * Нахождение спектра
     *
     * @return
     */
    public double[] getSpector() {
        return null;
    }

    /**
     * Вычисление интервала дискретизации спектра
     *
     * @return
     */
    public double getSampIntervSpector() {
        return 0;
    }

    /**
     * Нахождение корреляционной функции
     *
     * @return
     */
    public double[] getKorrFunc() {
        return null;
    }

    /**
     * Нахождение интервала дискретизации корреляционной функции
     *
     * @return
     */
    public double getSampIntervKorrFunc() {
        return 0;
    }

    //////////////////*Модуль микротвердости*///////////////////
 /* Четырехгранная пирамида с квадратным основанием.
     * type : 0 - сила в ньютонах , 1 - в килограмм-силах;
     * f :  нормальная нагрузка, приложенная к алмазному наконечнику Н(кгс);
     * h :  глубина отпечатка(мм).
     */
    public double[] indentorHeight(double proc[]) {
        double res[] = new double[proc.length];
        double h0 = getMaxValue(proc);
        for (int i = 0; i < proc.length; i++) {
            if (proc[i] == h0) {
                res[i] = 0.1;
            } else {
                res[i] = h0 - Math.abs(proc[i]);
            }
        }
        return res;
    }

    public double[] vickersHardness(double f[], double h[], int type,
            double thresholdVal) {
        double res[] = new double[h.length];
        for (int i = 0; i < f.length; i++) {
            res[i] = vickersHardness(f[i], h[i], type, thresholdVal);
        }
        return res;
    }

    public double vickersHardness(double f, double h, int type,
            double thresholdVal) {
        System.out.println("Height : " + h);
        if (f > thresholdVal) {
            double res = 0;;
            if (f > 0 && h > 0) {
                if (type == 0) {
                    res = 0.00386 * f / (0.000001 * h * h);
                } else {
                    res = 0.03784 * f / (0.000001 * h * h);
                }
                System.out.println("Hardness: " + res + " HV . Force : " + f + " N."
                        + " Depth :" + h);
                return res;
//            return (type == 0)
//                    ? 0.00386 * f / (0.000001 * h * h) : 0.03784 * f
//                    / (0.000001 * h * h);
            }
        }
        return 0;

    }
    /* Трехгранная пирамида.
     * type : 0 - сила в ньютонах , 1 - в килограмм-силах;
     * f :  нормальная нагрузка, приложенная к алмазному наконечнику Н(кгс);
     * h :  глубина отпечатка(мм).
     */

    public double triangleHardness(double f, double h, int type) {
        return (type == 0)
                ? 0.00387 * f / (0.000001 * h * h) : 0.03797 * f
                / (0.000001 * h * h);
    }
    /* Четырехгранная пирамида с ромбическим основанием.
     * type : 0 - сила в ньютонах , 1 - в килограмм-силах;
     * f :  нормальная нагрузка, приложенная к алмазному наконечнику Н(кгс);
     * h :  глубина отпечатка(мм).
     */

    public double rhombHardness(double f, double h, int type) {
        return (type == 0)
                ? 0.00141 * f / (0.000001 * h * h) : 0.01385 * f
                / (0.000001 * h * h);
    }
    /* Наконечник с бицилиндрическим основанием.
     * type : 0 - сила в ньютонах , 1 - в килограмм-силах;
     * f :  нормальная нагрузка, приложенная к алмазному наконечнику Н(кгс);
     * h :  глубина отпечатка(мм).
     */

    public double cilinderHardness(double f, double h, int type) {
        return (type == 0)
                ? 0.00744 * f / (Math.pow(h, 3.0 / 2.0))
                : 0.07292 * f / (Math.pow(h, 3.0 / 2.0));
    }

    /**
     * Центрирование процесса путем вычитания из него аппроксимированной прямой
     *
     * @param x - массив х
     * @param y - массив у
     * @return - центрированный процесс
     */
    public double[] centerProcess(double x[], double y[]) {
        double[] res = new double[y.length];
        double[][] approx = approximateFunc(x, y);
        for (int i = 0; i < res.length; i++) {
            res[i] = (y[i] - (x[i] * beta_1 + beta_0));
        }
        return res;
    }

    /**
     * Расчет микротвердости по Виккерсу по заданному значению нагрузки
     *
     * @param specified - значение нагрузки
     * @param x - массив глубин
     * @param y - массив значений микротвердости
     * @return
     */
    public double getVickersHardnessByValue(
            double y[], double x[], double specified, double thresholdVal) {
        int i = 0;
        if (specified < getMaxValue(y)) {
            while (specified > y[i++]) {
            }
            System.out.println("Y = " + y[i - 1] + " X = " + x[i - 1]);
            return vickersHardness(y[i - 1], x[i - 1], 0, thresholdVal);
        }
        return -1;
    }

    /**
     * Аппроксимация методом наименьших квадратов
     *
     * @param x - массив х
     * @param y - массив у
     * @return [0][0] - y[0], [0][1] - y[n] ; [1][0] - x[0], [1][1] - x[n];
     *
     */
    public static double[][] approximateFunc(double[] x, double y[]) {
        double[][] res = new double[2][2];
        if (x.length == y.length) {
            int n = 0;
            double sumx = 0.0, sumy = 0.0, sumx2 = 0.0;
            while (n < x.length) {
                sumx += x[n];
                sumx2 += x[n] * x[n];
                sumy += y[n];
                n++;
            }
            double xbar = sumx / n;
            double ybar = sumy / n;
            // second pass: compute summary statistics
            double xxbar = 0.0, yybar = 0.0, xybar = 0.0;
            for (int i = 0; i < n; i++) {
                xxbar += (x[i] - xbar) * (x[i] - xbar);
                yybar += (y[i] - ybar) * (y[i] - ybar);
                xybar += (x[i] - xbar) * (y[i] - ybar);
            }
            double beta1 = xybar / xxbar;
            double beta0 = ybar - beta1 * xbar;
            beta_0 = beta0;
            beta_1 = beta1;
            res[0][0] = beta1 * x[0] + beta0;
            res[0][1] = beta1 * x[x.length - 1] + beta0;
            res[1][0] = x[0];
            res[1][1] = x[x.length - 1];
            // print results
            if (beta0 > 0) {
//                System.out.println("y   = " + beta1 + " * x  + " + beta0);
            } else {
//                System.out.println("y   = " + beta1 + " * x  " + beta0);
            }
            int df = n - 2;
            double rss = 0.0;      // residual sum of squares
            double ssr = 0.0;      // regression sum of squares
            for (int i = 0; i < n; i++) {
                double fit = beta1 * x[i] + beta0;
                rss += (fit - y[i]) * (fit - y[i]);
                ssr += (fit - ybar) * (fit - ybar);
            }
            double R2 = ssr / yybar;
            double svar = rss / df;
            double svar1 = svar / xxbar;
            double svar0 = svar / n + xbar * xbar * svar1;
            svar0 = svar * sumx2 / (n * xxbar);
        } else {
            StendLogger.log(StendLogger.MSG_ERROR,
                    "Arrays have a different size");
        }
        return res;
    }

    /**
     * ****************Модуль шероховатости********************
     */
    public static double[][] findAvgArr(double x[], double[] proc) {
        double res[][] = new double[2][2];
        avg = getMean(proc);
        res[0][0] = avg;
        res[0][1] = avg;
        res[1][0] = x[0];
        res[1][1] = x[x.length - 1];
        return res;
    }

    public static double[][] upLimit(double x[], double[] proc) {
        double res[][] = new double[2][2];
        double max = getMaxValue(proc);
        res[0][0] = max;
        res[0][1] = max;
        res[1][0] = x[0];
        res[1][1] = x[x.length - 1];
        return res;
    }

    public static double[][] downLimit(double x[], double[] proc) {
        double res[][] = new double[2][2];
        double min = getMinValue(proc);
        res[0][0] = min;
        res[0][1] = min;
        res[1][0] = x[0];
        res[1][1] = x[x.length - 1];
        return res;
    }

    /**
     * Нахождение 5 наибольших выступов профиля
     *
     * @param baseLength - базовая длина
     * @return
     */
    public double[] findyD(double baseLength) {
        return findyD(baseLength, process);
    }

    public static double[] findyD(double baseLength, double proc[]) {
        double av = getMean(proc);
        double res[] = new double[5];
        double curMax = av;
        TreeSet ts = new TreeSet();
        for (int i = 1; i < proc.length - 1; i++) {
            if (proc[i] >= av) {
                if (proc[i] > proc[i + 1] && proc[i] > proc[i - 1]) {
                    curMax = proc[i];
                    // if (curMax - av < baseLength) {
                    ts.add(curMax - av);
                    // }
                }
            }
        }
        Iterator it = ts.descendingIterator();
        if (ts.size() > 4) {
            for (int i = 0; i < res.length; i++) {
                res[i] = (Double) it.next();
            }
        }
        return res;
    }

    /**
     * Нахождение 5 наибольших впадин профиля
     *
     * @param baseLength - базовая длина
     * @return
     */
    public double[] findyH(double baseLength) {
        return findyH(baseLength, process);
    }

    public static double[] findyH(double baseLength, double proc[]) {
        double av = getMean(proc);
        double res[] = new double[5];
        double curMin = av;
        TreeSet ts = new TreeSet();
        for (int i = 1; i < proc.length - 1; i++) {
            if (proc[i] < av) {
                if (proc[i] < proc[i + 1] && proc[i] < proc[i - 1]) {
                    curMin = proc[i];
                    // if (av - curMin < baseLength) {
                    ts.add(av - curMin);
                    // }
                }
            }
        }
        Iterator it = ts.iterator();
        if (ts.size() > 4) {
            for (int i = 0; i < res.length; i++) {
                res[i] = (Double) it.next();
            }
        }
        return res;
    }

    /**
     * Нахождение высоты неровностей профиля по 10 точкам.Сумма средних
     * абсолютных значений высот пяти наибольших выступов профиля и глубин пяти
     * наибольших впадин профиля в пределах базовой длины.
     *
     * @param yD - высоты 5 наибольших выступов профиля
     * @param yH - высоты 5 наибольших впадин профиля
     * @return
     */
    public double findRZ(double baseLength, double proc[]) {
        double yD[] = findyD(baseLength, proc);
        double yH[] = findyH(baseLength, proc);
        double sum = 0;
        for (int i = 0; i < yD.length; i++) {
            sum += yD[i] + yH[i];
        }
        return sum / 5.0;
    }

    /**
     * Нахождение наибольшей высоты выступа.
     *
     * @return
     */
    public double findRpmax() {
        return getMaxValue(process);
    }

    public static double findRpmax(double proc[]) {
        return getMaxValue(proc);
    }

    /**
     * Нахождение среднего арифметического отклонения профиля
     *
     * @return
     */
    public double findRA() {
        return findRA(process);
    }

    public static double findRA(double proc[]) {
        double av = getMean(proc);
        System.out.println("Mean -> " + av);
        double sum = 0;
        for (int i = 0; i < proc.length; i++) {
            sum += Math.abs(proc[i] - av);
        }
        return sum / proc.length;
    }

    /**
     * Нахождение наибольшей высоты профиля.
     *
     * @return
     */
    public double findRmax() {
        return getMaxValue(process) - getMinValue(process);

    }

    public static double findRmax(double[] proc) {
        return getMaxValue(proc) - getMinValue(proc);
    }

    /**
     * Нахождение среднего шага неровностей.
     *
     * @return
     */
    public static double findSm(double x[], double proc[]) {
        double gistLine = CoefConfigurator.getConf().getSensorCoefProp(2);
        double av = getMean(proc);
        ArrayList indexes = new ArrayList();
        double sum = 0;
        int cnt = 0;
        for (int i = 0; i < proc.length - 1; i++) {
            if (proc[i] <= av && proc[i + 1] > av + gistLine) {
                indexes.add(new Integer(i));
                if (cnt > 0) {
                    sum += x[(Integer) indexes.get(cnt)]
                            - x[(Integer) indexes.get(cnt - 1)];
                }
                cnt++;
            }
        }
        return sum / (double) cnt;
    }

    /**
     * Нахождение опорной длины профиля по средней линии.
     *
     * @return
     */
    public double findTm(double[] x, double[] proc, double baseLengths) {
        double gistLine = CoefConfigurator.getConf().getSensorCoefProp(2);
        double sum = 0;
        int num = 0;
        if (num > -1 && num < 5) {
            double slideLine = getMean(proc);
            double firstPoint = 0;
            boolean isAbove = false;
            for (int i = 0; i < proc.length - 1; i++) {
                if (proc[i] >= slideLine && !isAbove) {
                    isAbove = true;
                    firstPoint = x[i];
                }
                if (proc[i + 1] < slideLine && proc[i]
                        >= slideLine && isAbove) {
                    sum += x[i] - firstPoint;
                    isAbove = false;
                } else if (isAbove && i == proc.length - 1) {
                    sum += x[x.length - 1] - firstPoint;
                }
            }
        } else {
            StendLogger.log(StendLogger.MSG_ERROR, "Index out of bounds in Base"
                    + "length's array");
            return -1;
        }
        return sum / (baseLengths * 1000);
    }

    /**
     * Функция, осуществляющая "срез" уровней с профилограммы поверхности,
     * составляющая на основе этих срезов кривую опорной поверхности.
     *
     * @param x
     * @param proc
     * @param nsensor
     * @return
     */
    public double[][] buildGraph(double[] x, double[] proc, int nsensor) {
        double res[][] = null;
        int arrLen = 0;
        try {
            double coef = CoefConfigurator.getConf().getSensorCoefProp(nsensor);
            double max = getMaxValue(proc) + coef / 2;
            double min = getMinValue(proc) - coef / 2;
            int j = 0;
            int levelsCnt = (int) (Math.round((max - min) / coef) + 1);
            ArrayList cross[] = new ArrayList[levelsCnt];
            arrLen = cross.length;
            double levels[] = new double[levelsCnt];
            res = new double[2][levelsCnt];
            double sum = 0;
            for (int i = 0; i < levelsCnt; i++) {
                levels[i] = max - coef * i;
                cross[i] = new ArrayList<Double>();
            }
            for (int i = 0; i < proc.length - 1; i++) {
                if (proc[i] > proc[i + 1]) {
                    max = proc[i];
                    min = proc[i + 1];
                } else {
                    max = proc[i + 1];
                    min = proc[i];
                }
                j = 0;
                while (levels[j] > max) {
                    j++;
                }
                if (j < levelsCnt) {
                    while (levels[j] > min) {
                        cross[j].add(new Double(x[i]));
                        j++;
                    }
                }
            }
            for (int i = 0; i < cross.length; i++) {
                sum = 0;
                j = 0;
                if (levels[i] < proc[0] && cross[i].size() != 0) {
                    sum += (Double) cross[i].get(0) - x[0];
                    j++;
                }
                while (j < cross[i].size()) {
                    sum += ((j + 1 < cross[i].size())
                            ? (Double) cross[i].get(j + 1)
                            : x[x.length - 1]) - (Double) cross[i].get(j);
                    j += 2;
                }
                res[1][i] = sum;
            }
            res[1][cross.length - 1] = x[x.length - 1] - x[0];
            System.arraycopy(levels, 0, res[0], 0, levelsCnt);
        } catch (Exception ex) {
            System.out.println("Message: " + ex.getMessage());
            ex.printStackTrace();
            return new double[1][arrLen - 1];
        }
        return res;
    }

    /**
     * Нахождение маслоемкости поверхности
     *
     * @return
     */
    public double findOilAbsorption(double x[], double[] proc, int nsensor) {
        double gistLine = CoefConfigurator.getConf().getSensorCoefProp(nsensor);
        int point = x.length / 3;
        double sum = 0;
        double yAv = 0;
        double value = 0.03 * (getMaxValue(proc) - getMinValue(proc));
        int i = 0;
        for (i = point; i < 2 * point && i < proc.length; i++) {
            sum += (proc[i + 1] - proc[i]) / (x[i + 1] - x[i]);
            yAv += (proc[i]);
        }
        double av = sum / point;
        yAv = yAv / point;
        double b = yAv - av * x[x.length / 2];
        i = 0;
        while (i < proc.length && i < x.length && proc[i] - (av * x[i] + b) > value) {
            i++;
        }
        return proc[0] - proc[i];
    }

    /**
     * Нахождение величины приработочного ресурса
     *
     * @return
     */
    public double findResourceValue(double x[], double[] proc, int nsensor) {
        int indx = 0;
        try {
            double gistLine = CoefConfigurator.getConf().getSensorCoefProp(nsensor);
            int point = x.length / 3;
            double sum = 0;
            double yAv = 0;
            double value = 0.03 * (getMaxValue(proc) - getMinValue(proc));
            int i = 0;
            for (i = point; i < 2 * point && i < proc.length; i++) {
                sum += (proc[i + 1] - proc[i]) / (x[i + 1] - x[i]);
                yAv += (proc[i]);
            }
            double av = sum / point;
            yAv = yAv / point;
            double b = yAv - av * x[x.length / 2];
            i = x.length - x.length / 3;
            while (i < proc.length && i < x.length && proc[i] - (av * x[i] + b) > value) {
                i++;
            }
            indx = i;
        } catch (Exception ex) {
            System.out.println("Exception message : " + ex.getLocalizedMessage());
            ex.printStackTrace();
            return 0;
        }
        return proc[0] - proc[indx];
    }

    /**
     * *******************Модуль волнистости**********************
     */
    /**
     * Нахождение маскимальной высоты волн
     *
     * @return
     */
    public static double findAverageWavesHeight(double[] proc) {
        return getMaxValue(proc) - getMinValue(proc);
    }

    public double findAverageWavesHeight() {
        return getMaxValue(process) - getMinValue(process);
    }

    /**
     * Нахождение среднего шага волн
     *
     * @return
     */
    public double findAverageWavesStep(double[] x, double[] proc,
            double baseLength) {
        int sectionNum = (int) (x[x.length - 1] / (baseLength + 1));
        double res[] = new double[sectionNum];
        double gistLine = CoefConfigurator.getConf().getSensorCoefProp(2);
        double av = getMean(proc);
        ArrayList indexes = new ArrayList();
        double sum = 0;
        int it = 0;
        int cnt = 0;
        for (int i = 0; i < proc.length - 1; i++) {
            if (proc[i] < av && proc[i + 1] > av + gistLine) {
                indexes.add(new Integer(i));
                if (cnt > 0) {
                    sum += x[(Integer) indexes.get(cnt)]
                            - x[(Integer) indexes.get(cnt - 1)];
                }
                cnt++;
            }
        }
//        if (cnt < 5) {
//            double X = (sum / (double) cnt) * 5;
//            JOptionPane.showMessageDialog(null,
//                    "Рекомендуется увеличить базовую длину до" + X + " мм",
//                    "Базовая длина слишком мала", JOptionPane.OK_OPTION);
//        }
//        if ((sum / cnt) / findAverageWavesHeight(proc) < 40) {
//            JOptionPane.showMessageDialog(null,
//                    "Полученная профилограмма характеризует не волнистость,"
//                    + " а шероховатость поверхности. Рекомендуется увеличить"
//                    + " длину трассы сканирования",
//                    "Длина трассы сканирования слишком мала",
//                    JOptionPane.OK_OPTION);
//        }
        return sum / cnt;
    }

    /**
     * *******************Модуль склерометрирования***********
     */
    /**
     * Расчет энергии активации
     *
     * @param Vm - молярный объем материала поверхностного слоя, мм3/моль;
     * @param Ft - сила царапания, Н;
     * @param h - глубина внедрения индентора в поверхность.
     * @return
     */
    public double[] findUltimateEnergy(double Ft[], double h[], double Vm) {
        double res[] = new double[h.length];
        for (int i = 0; i < res.length; i++) {
            res[i] = findUltimateEnergy(Ft[i], h[i], Vm);
        }
        return res;
    }

    public double findUltimateEnergy(double Ft, double h, double Vm) {
        return (0.28 * Ft * Vm * 1000) / (h * h);
    }

    public double findSpecificUltEnergy(double energy, double Vm, double p) {
        return (energy * 1000000000 / (Vm * p));
    }

    /**
     * Нахождение коэффициента трения
     *
     * @param tanF
     * @param normalF
     * @return
     */
    public double findFrictionCoef(double tanF, double normalF) {
        return tanF / normalF;
    }

    /**
     * *************Определение энергии пластической деформации************
     */
    public double frictionPath(int amplitude, int doubleMoves) {
        return amplitude * doubleMoves / 1000;
    }

    /**
     * @return
     */
    public double lineErosion() {

        return 0;
    }

    /**
     * *************Модуль прогнозирования остаточного ресурса************
     */
    /**
     * Нахождение остаточного ресурса
     *
     * @param limit - граничная величина
     * @param x - временные отрезки
     * @param proc - значения энергий
     * @return
     */
//    public double findRemainingResource() {
//        return findRemainingResource(limit, x[], process);
//    }
    public static double findRemainingResource(double limit, double x[],
            double proc[]) {
        approximateFunc(x, proc);
        return (((limit - beta_0) / beta_1) - x[x.length - 1])
                / ((limit - beta_0) / beta_1);
    }

    /**
     * Нахождение безопасного ресурса
     *
     * @param limit - граничная величина энергии
     * @param x - временные отрезки
     * @param proc - значения энергий
     * @return
     */
    public static double findSafeResource(double limit, double x[],
            double proc[]) {
        double tg = (proc[proc.length - 1] - proc[0]) / (x[x.length - 1] - x[0]);
        double b = (x[0] * (proc[proc.length - 1] - proc[0]))
                / (x[x.length - 1] - x[0]);
        return ((limit - b) / tg - x[x.length - 1]) / ((limit - b) / tg);
    }

    public double findAverageEvasion() {
        return 0;
    }

    /**
     * Нахождение прогнозируемого срока службы
     *
     * @param limit - граничное значение энергии
     * @param x - значения времен
     * @param proc - значения энергии
     * @return
     */
    public static double findServicePeriod(double limit, double x[],
            double proc[]) {
        approximateFunc(x, proc);
        return (limit - beta_0) / beta_1;
    }

    /**
     * Центрирование процесса путем разложения функции в ряд Фурье
     *
     * @param x
     * @param proc
     * @param k
     * @return
     */
    public double[] fourierTransform(double x[], double proc[], int k,
            double divCoef) {
        double l = x[x.length - 1] / 2 - x[0] / 2;
//        int cutThis = (int) (proc.length * val);
        double[] res = new double[proc.length];
        double mean = getMean(proc);
        double sum = 0;
        double a0 = a0(proc, l);
        double pi = Math.PI;
        for (int i = 0; i < x.length; i++) {
            for (int j = 1; j < k; j++) {
                sum += an(proc, j, l, divCoef) * Math.cos((j * pi * i / divCoef) / l)
                        + bn(proc, j, l, divCoef) * Math.sin((j * pi * i / divCoef) / l);
            }
            res[i] = a0 / 2.0 + sum;
            res[i] = proc[i] - res[i];
            sum = 0;
        }

//        double myarr[] = new double[(int) (proc.length * 0.9)];
//        System.arraycopy(res, (int) cutThis, myarr, 0, myarr.length);
//        double avg = getMean(myarr);
//        for (int i = 0; i < proc.length; i++) {
//            if (i < cutThis || i > proc.length - cutThis) {
//                res[i] = proc[i] - mean + avg;
//            }
//        }
        return res;
    }

    /**
     *
     * @param x
     * @param y
     * @param k
     * @param divCoef
     * @return
     */
    public double[] getFourierCentering(double x[], double y[], int k,
            double divCoef) {
        double rfy[] = null;
        int len = 0;
        try {
            double dxl = Math.abs(x[1] - x[0]);
            double dxp = Math.abs(x[x.length - 1] - x[x.length - 2]);

            double ex = Math.abs((x[x.length - 1] - x[0]) * 0.1);
            int dp = 0;
            int dl = 0;

            if (dxp != 0) {
                dp = (int) (ex / dxp);
            }

            if (dxl != 0) {
                dl = (int) (ex / dxl);
            }

            int nlen = x.length + dp + dl;

            double dyl = 0;
            double dyp = 0;
            len = y.length;
            int max = y.length - 1;

            for (int i = 0; i < 5; i++) {
                dyl += (y[i + 1] - y[i]) / (x[i + 1] - x[i]);
                dyp += (y[i + len - 5] - y[i + len - 6]) / (x[i + len - 5]
                        - x[i + len - 6]);
            }
            dyl /= 5;
            dyp /= 5;

            double ny[] = new double[nlen];
            double nx[] = new double[nlen];

            for (int i = 0; i < ny.length; i++) {
                if (i >= dl && i <= dl + max) {
                    ny[i] = y[i - dl];
                    nx[i] = x[i - dl];
                } else if (i < dl) {
                    ny[i] = dyl * (dl - i);
                    nx[i] = dxl * (dl - i);
                } else if (i > dl + max) {
                    ny[i] = dyp * (i - max - dl);
                    nx[i] = dxp * (i - max - dl);
                }
            }

            double nfyk[] = fourierTransform(nx, ny, k, divCoef);
            rfy = new double[len];

            for (int i = 0; i < rfy.length; i++) {
                rfy[i] = nfyk[i + dl];
            }
        } catch (Exception ex) {
            System.out.println("Exception message : " + ex.getLocalizedMessage()
                    + " Stack trace: ");
            ex.printStackTrace();
            return new double[len];
        }
        System.out.println("Success! There are no exceptions.");
        return rfy;
    }

    public double[][] rabbiFunction(double x[], double proc[], double start,
            double end) {
        int min = 0;
        int max = 0;
        boolean isMinFinded = false;
        boolean isMaxFinded = false;
        for (int i = 0; i < x.length; i++) {
            if (start < x[i] && !isMinFinded) {
                min = i + 1;
                isMaxFinded = true;
            }
            if (end < x[i] && !isMaxFinded) {
                max = i;
                isMaxFinded = true;
                break;
            }
        }
        double res[][] = new double[2][2];
        res[0][0] = proc[min];
        res[0][1] = proc[max];
        res[1][0] = x[min];
        res[1][1] = x[max];

        return res;
    }

    /**
     * Коэффициент а0 ряда Фурье
     *
     * @param proc
     * @param l
     * @return
     */
    public double a0(double proc[], double l) {
        double sum = 0;
        for (int i = 0; i < proc.length; i++) {
            sum += proc[i];
        }
        return sum / l;
    }

    /**
     * Коэффициент аn ряда Фурье
     *
     * @param proc
     * @param n
     * @param l
     * @return
     */
    public double an(double proc[], double n, double l, double divCoef) {
        double sum = 0;
        double pi = Math.PI;
        for (int i = 0; i < proc.length; i++) {
            sum += proc[i] * Math.cos((n * pi * i / divCoef) / l);
        }
        return sum / l;
    }

    /**
     * Коэффициент bn ряда Фурье
     *
     * @param proc
     * @param n
     * @param l
     * @return
     */
    public double bn(double proc[], double n, double l, double divCoef) {
        double sum = 0;
        double pi = Math.PI;
        for (int i = 0; i < proc.length; i++) {
            sum += proc[i] * Math.sin((n * pi * i / divCoef) / l);
        }
        return sum / l;
    }

    public double getPk(int k, double x) {
        double sum = 0;
        double as = 0;
        //k = k /2 ;
        for (int s = 0; s < k / 2; s++) {
            as = (Math.pow(-1, s) * ((Math.sqrt(2.0 * k + 1)
                    * factorial(2.0 * k - 2.0 * s)))
                    / (Math.sqrt(2) * 2 * k * factorial(s) * factorial(k - s)
                    * factorial(k - 2.0 * s)));
            sum += as * Math.pow(x, k - 2 * s);
        }
        System.out.println("getting pk -> " + sum);
        return sum;
    }

    public double[][] corrFunc(double[] x, double[] proc, double ordNum) {
        double smpIntrv = CoefConfigurator.getConf().getSensorCoefProp(2);
        double mean = getMean(proc);
        double disp = getDisp(proc);
        double iter = 0;
        double res[][] = new double[2][(int) ordNum];
        double sum = 0;
        for (int j = 0; j < ordNum; j++) {
            for (int i = 0; i < proc.length - j; i++) {
                sum += (proc[i] - mean) * (proc[i + j] - mean);
            }
            // px[j] = Math.pow((len - j - 1) * dispers, -1) * sum;

            res[0][j] = (1.0 / ((proc.length - j - 1) * disp)) * sum;
            res[1][j] = iter;
            iter += smpIntrv;
            sum = 0;
        }

        return res;
    }

    public double[] powerSpectrum(double corfunc[]) {

        return null;
    }

    public static double[] getValues(int len) {
        DataProcessor dp = new DataProcessor();
        double arr[] = new double[len];
        Random rand = new Random();
        for (int i = 0; i < arr.length; i++) {

            double r = rand.nextInt(255) + 100 * (Math.sin(i / 50) + 1) + 1;
            //  arr[i] =  (r <192 && r>64) ? 0.2*(r -128)+128 : r;
            arr[i] = r;
        }
        return arr;
    }

    /**
     * Нахождение факториала числа
     *
     * @param val
     * @return
     */
    public static double factorial(double val) {
        if (val == 0) {
            return 1;
        } else {
            return val * factorial(val - 1);
        }
    }

    public static double findOrdinatesNum(int modelNum, double lambda,
            double omega) {
        double ordNum = 0;
        switch (modelNum) {
            case 1: {
                ordNum = 9;
            }
            break;
            case 2: {
                ordNum = 13;
            }
            break;
            case 3: {
                ordNum = 19;
            }
            break;
            case 4: {
                ordNum = (47.0 * omega) / (2.0 * Math.PI * lambda);
            }
            break;
            case 5: {
                ordNum = (47.0 * omega) / (2.0 * Math.PI * lambda);
            }
            break;
            case 6: {
                ordNum = (47.0 * omega) / (2.0 * Math.PI * lambda);
            }
            break;
            default:
                break;
        }
        return Math.round(ordNum);
    }

    public static double findGamma(double k, double sampIntrv) {
        return 0.4 / ((2 * k + 1) * sampIntrv);
    }

    public static double findInverseLegNorm(int k, double gamma) {
        return 1 / 2 * gamma * (2 * k + 1);
    }

    public static double findSamplingInterval(double omega,
            double error, int modelNum, double lambda) {
        double derivative2 = 0;
        switch (modelNum) {
            case 2: {
                derivative2 = -lambda * lambda;
            }
            break;
            case 3: {
                derivative2 = 3 * lambda * lambda;
            }
            break;
            case 4: {
                derivative2 = lambda * lambda - omega * omega;
            }
            break;
            case 5: {
                derivative2 = -lambda * lambda - omega * omega;
            }
            break;
            case 6: {
                derivative2 = -lambda * lambda - omega * omega;
            }
            break;
            default:
                break;
        }
        return Math.sqrt(8 * error / Math.abs(derivative2));
    }

    public static double lager(double t, double gm, double k) {
        double res = 0;
        if (k == 0) {
            res = Math.exp(-gm / 2 * t);
        } else if (k == 1) {
            res = Math.exp(-gm / 2 * t) * (1 - gm * t);
        } else {
            for (int i = 0; i < k + 1; i++) {
                res += (factorial(k) * Math.pow(-gm * t, i)
                        * Math.exp(-(gm * t / 2.0)))
                        / (factorial(i) * factorial(k - i)
                        * factorial(i));
            }
        }
        return res;
    }

    public static double lager0(double t, double gm) {
        return Math.exp(-gm / 2 * t);
    }

    public static double lager1(double t, double gm) {
        return Math.exp(-gm / 2 * t) * (1 - gm * t);
    }

    public static double lagerI0(double t, double gm) {
        return -2 / gm * Math.exp(-gm / 2 * t);
    }

    public static double lagerI1(double t, double gm) {
        return Math.exp(-gm / 2 * t) * (2 * t + 2 / gm);
    }

    public static double lagerIT0(double t, double gm) {
        return (-4 * Math.exp(-gm / 2 * t) * (gm * t / 2 + 1)) / (gm * gm);
    }

    public static double lagerIT1(double t, double gm) {
        return Math.exp(-gm / 2 * t) * (6 * t / gm + 12
                / (gm * gm) + 2 * t * t);

    }

    public static double recLagI(double t, double gm, double k) {
        double sum = 0;
        if (k == 0) {
            return lagerI0(t, gm);
        } else if (k == 1) {
            return lagerI1(t, gm);
        } else {
            for (int i = 0; i < k; i++) {
                sum += recLagI(t, gm, i);
            }
            return -2 * sum - 2 * lager(t, gm, k) / gm;
        }
    }

    public static double recLagIT(double t, double gm, double k) {
        if (k == 0) {
            return lagerIT0(t, gm);
        } else if (k == 1) {
            return lagerIT1(t, gm);
        } else {
            return -((k + 1) / gm) * recLagI(t, gm, k + 1)
                    + (2 * k + 1) * recLagI(t, gm, k) / gm - k
                    * recLagI(t, gm, k - 1) / gm;
        }
    }

    public static double getRecIntegral(double t, double gm, double k,
            boolean leg, boolean withT) {
        if (leg) {
            if (withT) {
                // System.out.println("Leg with t");
                return legRecIntegralT(t, gm, k);

            } else {
                // System.out.println("Leg without t");
                return legRecIntegral(t, gm, k);
            }
        } else {
            if (withT) {
                // System.out.println("Lag with t");
                return recLagIT(t, gm, k);
            } else {
                //  System.out.println("Lag without t");
                return recLagI(t, gm, k);
            }
        }
    }

    public static double leg(double t, double gm, double k) {
        double res = 0;
        if (k == 0) {
            res = Math.exp(-t * gm);
        } else {
            for (int i = 0; i < k + 1; i++) {
                res = res + factorial(k) / (factorial(k - i) * factorial(i))
                        * factorial(k + i) / (factorial(k) * factorial(i))
                        * Math.pow(-1, i) * Math.exp(-(2 * i + 1) * gm * t);
            }
        }
        return res;
    }

    //Интеграл 0 порядка без т  
    public static double legI0(double t, double gm) {
        return -1 / gm * Math.exp(-gm * t);
    }

    //    return  2*Math.exp(-3 * gm * t)/3*gm - Math.exp(- gm * t)/gm ; 
    //Интеграл 1 порядка без т
    public static double legI1(double t, double gm) {
        return -1 / gm * (1 - 2.0 / 3.0 * Math.exp(-2 * gm * t)) * Math.exp(-gm * t);
    }

    //Интеграл 0 порядка с участием т
    public static double legIT0(double t, double gm) {
        return -(t / gm + 1 / (gm * gm)) * Math.exp(-gm * t);
    }

    //Интеграл 1 порядка с участием т 
    public static double legIT1(double t, double gm) {
        return -(t / gm + 1 / (gm * gm)) * Math.exp(-gm * t)
                + 2 * (t / (3.0 * gm) + 1.0 / (9.0 * gm * gm))
                * Math.exp(-3.0 * gm * t);
    }

    //Рекурсивный поиск интеграла без т
    public static double legRecIntegral(double t, double gm, double k) {
        if (k == 0) {
            return legI0(t, gm);
        } else if (k == 1) {
            return legI1(t, gm);
        } else {
            return 2 * (2 * k - 1) / (2 * k + 1)
                    * legRecIntegral(t, gm, k - 1)
                    - (2 * k - 3) / (2 * k + 1)
                    * legRecIntegral(t, gm, k - 2)
                    - 1 / (gm * (2 * k + 1)) * (leg(t, gm, k)
                    - leg(t, gm, k - 2));
        }
    }
    //Рекурсивный поиск интеграла с участием т

    public static double legRecIntegralT(double t, double gm, double k) {
        if (k == 0) {
            return legIT0(t, gm);
        } else if (k == 1) {
            //   System.out.println("In >>>>");
            return legIT1(t, gm);
        } else {
            return 2 * (2 * k - 1) / (2 * k + 1)
                    * legRecIntegralT(t, gm, k - 1)
                    - (2 * k - 3) / (2 * k + 1)
                    * legRecIntegralT(t, gm, k - 2)
                    - 1 / (gm * (2 * k + 1))
                    * (t * (leg(t, gm, k) - leg(t, gm, k - 2))
                    - legRecIntegral(t, gm, k)
                    + legRecIntegral(t, gm, k - 2));
        }
    }

    public static double[] findA(double p[], double b[], double t[]) {
        double a[] = new double[b.length];
        for (int i = 0; i < a.length; i++) {
            a[i] = p[i] - b[i] * t[i];
            //       System.out.println("a[" + i +  "] = " +a[i] );  
        }
        return a;
    }
    //Находим Bi

    public static double[] findB(double[] p, double sampIntrv) {
        double b[] = new double[p.length - 1];
        for (int i = 0; i < p.length - 1; i++) {
            b[i] = (p[i + 1] - p[i]) / sampIntrv;
            //       System.out.println("b[" + i +  "] = " +b[i] );   
        }
        return b;
    }
    //Находим массив т-итых

    public static double[] findT(double numOrd, double sampIntrv) {
        double t[] = new double[(int) numOrd];
        double iter = sampIntrv;
        for (int i = 0; i < t.length; i++) {
            t[i] = sampIntrv - iter;
            sampIntrv += iter;
            //      System.out.println("T[" + i + "] = "  + t[i]);
        }
        return t;
    }
    //Поиск бетта-коффициентов

    public static double[] findBetta(double t[], double a[],
            double b[], double k, double gm, boolean isLeg) {
        double[] Betta = new double[(int) (k)];
        double sum = 0;
        for (int i = 0; i < k; i++) {
            for (int j = 0; j < t.length - 1; j++) {
                if (isLeg) {
                    sum += a[j] * (getRecIntegral(t[j + 1], gm, i, true, false)
                            - getRecIntegral(t[j], gm, i, true, false))
                            + b[j] * (getRecIntegral(t[j + 1], gm, i, true, true)
                            - getRecIntegral(t[j], gm, i, true, true));
                } else {
                    sum += a[j] * (getRecIntegral(t[j + 1], gm, i, false, false)
                            - getRecIntegral(t[j], gm, i, false, false))
                            + b[j] * (getRecIntegral(t[j + 1], gm, i, false, true)
                            - getRecIntegral(t[j], gm, i, false, true));
                }
            }
            if (isLeg) {
                Betta[i] = 2 * gm * (2 * i + 1) * sum;
            } else {
                Betta[i] = gm * sum;
            }

            System.out.println("Betta [" + i + "]  is - > " + Betta[i]);
            sum = 0;
        }
        return Betta;
    }

    public static double[] findBetta(double t[], double a[],
            double b[], double k, double gm) {
        double[] Betta = new double[(int) (k)];
        double sum = 0;
        for (int i = 0; i < k; i++) {
            for (int j = 0; j < t.length - 1; j++) {
                sum += a[j] * (legRecIntegral(t[j + 1], gm, i)
                        - legRecIntegral(t[j], gm, i))
                        + b[j] * (legRecIntegralT(t[j + 1], gm, i)
                        - legRecIntegralT(t[j], gm, i));
            }
            Betta[i] = 2 * gm * (2 * i + 1) * sum;
            System.out.println("Betta [" + i + "]  is - > " + Betta[i]);
            sum = 0;
        }
        return Betta;
    }

    public static double[] approxFuncOrd(double Betta[], double ti[],
            double gm, double px[]) {
        double[] Kx = new double[ti.length];
        double sum = 0;
        for (int i = 0; i < ti.length; i++) {
            for (double j = 0; j < Betta.length; j++) {
                sum += Betta[(int) j] * leg(ti[i], gm, j);
            }
            Kx[i] = sum;
            System.out.println("Kx[" + i + "] = " + Kx[i] + "   "
                    + " px[" + i + "] = " + px[i]);
            sum = 0;
        }
        return Kx;
    }

    public static double[] approxFuncOrd(double Betta[], double ti[],
            double gm, boolean isLeg) {
        double[] Kx = new double[ti.length];
        double sum = 0;
        for (int i = 0; i < ti.length; i++) {
            for (double j = 0; j < Betta.length; j++) {
                if (isLeg) {
                    sum += Betta[(int) j] * leg(ti[i], gm, j);
                } else {
                    sum += Betta[(int) j] * lager(ti[i], gm, j);
                }
            }
            Kx[i] = sum;
            System.out.println("Kx[" + i + "] = " + Kx[i]);
            //     + " px[" + i + "] = " + px[i]);
            sum = 0;
        }
        return Kx;
    }

    public static double[] approxTract(double[] cor, double k, boolean isLeg) {
        double smpIntrv = cor[1] - cor[0];
        gm = isLeg ? 0.4 / ((2 * k + 1) * smpIntrv) : 0.8 / smpIntrv + 0.2;
        double b[] = findB(cor, smpIntrv);
        double t[] = findT(cor.length, smpIntrv);
        double a[] = findA(cor, b, t);
        betta = findBetta(t, a, b, k, gm, isLeg);
        double aprroxres[] = approxFuncOrd(betta, t, gm, isLeg);
        return aprroxres;
    }

    public static double[][] findLegPowerSpectrum(
            double omega, double step) {
        int length = (int) (2 * (omega / step));
        double res[][] = new double[2][length];
        double iter = omega;
        double S[] = new double[length];
        double sum = 0;
        double FiSum = 0;
        omega = 0;
        for (int i = 0; i < S.length; i++) {
            for (int j = 0; j < betta.length; j++) {
                if (j == 0) {
                    FiSum = 0;
                } else {
                    for (int l = 0; l < j; l++) {
                        FiSum += Math.atan(omega / (2 * gm * (l + 1)));
                    }
                }
                sum += betta[j] * (1.0 / (2 * j + 1))
                        * Math.cos(Math.atan(omega / (2 * gm * (j + 1))))
                        * Math.cos(Math.atan(omega
                        / (2 * gm * (j + 1))) + 2 * FiSum);
                FiSum = 0;
            }
            res[0][i] = (1.0 / (Math.PI * gm)) * sum;
            res[1][i] = omega;
            sum = 0;
            omega += step;
        }
        return res;
    }

    public static double[] findLagPowerSpectrum(double Betta[], double gm,
            double omega, double step) {
        int length = (int) (2 * (omega / step));
        double iter = omega;
        double S[] = new double[length];
        double sum = 0;
        double fi = 0;
        omega = 0;
        for (int i = 0; i < S.length; i++) {
            fi = Math.atan((2 * omega) / gm);
            for (int j = 0; j < Betta.length; j++) {
                sum += Betta[i] * (Math.pow(-1, j)) * Math.cos((2 * j + 1) * fi);
            }
            S[i] = (2.0 * Math.cos(fi) / (Math.PI * gm)) * sum;
            System.out.println("S [" + i + "]  - > " + S[i]);
            sum = 0;
            omega += step;
        }
        return S;
    }

    /**
     *
     * @param y
     * @param delta
     * @return
     */
    public double[] addDelta(double y[], double delta) {
        for (int i = 0; i < y.length; i++) {
            y[i] += delta;
        }
        return y;
    }

    /**
     * Функция, определяющая индекс первого элемента, вышедшего за указанный
     * порог.
     *
     * @param y - массив данных для проверки.
     * @param gran - пороговое значение.
     * @param type - тип условия проверки.
     * @return - индекс первого элемента из массива, превосходящего заданный
     * порог. В случае ошибки возвращается -1.
     */
    public int limitDetector(double y[], double gran, int type) {
        for (int i = 1; i < y.length; i++) {
            if ((y[i - 1] > gran && y[i] <= gran && type == 0)
                    || (y[i - 1] < gran && y[i] > gran && type == 1)
                    || ((y[i - 1] > gran && y[i] <= gran)
                    || (y[i - 1] < gran && y[i] > gran) && type == 2)) {
                return i;
            }
        }
        return -1;
    }
    /////////////////////Окончание
}
